--- /dev/null
+testdir/
+Dockerfile
+*.log
+__pycache__/
-FROM ubuntu:18.04
+FROM ubuntu:18.04 as builder
COPY ./main.c ./main.c
COPY ./src/ ./src/
COPY ./include/ ./include/
FROM python
RUN apt-get update && \
- apt-get install -y valgrind
-COPY --from=0 ./Release/siridb-server /Release/siridb-server
+ apt-get install -y \
+ valgrind \
+ libuv1 \
+ libpcre2-8-0 && \
+ wget https://github.com/SiriDB/siridb-admin/releases/download/1.1.3/siridb-admin_1.1.3_linux_amd64.bin -O /usr/local/bin/siridb-admin && \
+ chmod +x /usr/local/bin/siridb-admin
+COPY --from=builder ./Release/siridb-server /Release/siridb-server
+COPY --from=builder /usr/lib/x86_64-linux-gnu/libcleri* /usr/lib/x86_64-linux-gnu/
COPY ./itest/ /itest/
WORKDIR /itest
RUN pip install -r requirements.txt
-CMD [ "python", "test_select.py" ]
\ No newline at end of file
+CMD [ "python", "run_all.py", "-m", "-b=Release" ]
#!/usr/bin/python3
from testing import run_test
from testing import Server
+from testing import parse_args
from test_cluster import TestCluster
from test_group import TestGroup
from test_list import TestList
from test_buffer import TestBuffer
-Server.BUILDTYPE = 'Release'
-
if __name__ == '__main__':
- # run_test(TestCluster())
+ parse_args()
run_test(TestCompression())
run_test(TestGroup())
run_test(TestList())
async def run(self):
await self.client0.connect()
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
'Group name should be at least 1 characters.'):
await self.client0.query('create group `` for /c.*/')
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
'Group name should be at least 1 characters.'):
await self.client0.query('create group `` for /c.*/')
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
'Group name should be at most [0-9]+ characters.'):
await self.client0.query(
await self.client0.query('create group `a` for /a.*/'),
{'success_msg': "Successfully created group 'a'."})
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
'Group \'a\' already exists.'):
await self.client0.query('create group `a` for /a.*/')
result = await self.client1.query('list groups series')
self.assertEqual(result.pop('groups'), [[2], [2], [2]])
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
"Cannot compile regular expression.*"):
result = await self.client1.query('create group `invalid` for /(/')
result = await self.client0.query('list series `a`, `two` & "c2"')
self.assertEqual(sorted(result.pop('series')), [['c2']])
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
"Cannot compile regular expression.*"):
await self.client1.query('alter group `a` set expression /(.*/')
# await self.client0.query('drop group `b`')
await self.client0.query('drop group `c`')
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
'Group \'c\' does not exist.'):
await self.client0.query('drop group `c`')
await self.client0.query('list series /.*/ ^ /a.*/ ^ /.*/')
await self.client0.query('alter database set list_limit 5000')
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
'Limit must be a value between 0 and 5000 '
'but received: 6000.*'):
from testing import SiriDB
from testing import TestBase
from testing import UserAuthError
+from testing import parse_args
DATA = {
await self.client0.query('select difference() from "one"'),
{'one': []})
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
'Regular expressions can only be used with.*'):
await self.client0.query('select filter(~//) from "log"')
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
'Cannot use a string filter on number type.'):
await self.client0.query('select filter(//) from "aggr"')
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
'Cannot use mean\(\) on string type\.'):
await self.client0.query('select mean(1w) from "log"')
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
'Group by time must be an integer value larger than zero\.'):
await self.client0.query('select mean(0) from "aggr"')
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
'Limit must be an integer value larger than zero\.'):
await self.client0.query('select limit(6 - 6, mean) from "aggr"')
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
'Cannot use a string filter on number type\.'):
await self.client0.query(
'select * from "aggr" '
'merge as "t" using filter("0")')
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
'Cannot use difference\(\) on string type\.'):
await self.client0.query('select difference() from "log"')
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
'Cannot use derivative\(\) on string type\.'):
await self.client0.query('select derivative(6, 3) from "log"')
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
'Cannot use derivative\(\) on string type\.'):
await self.client0.query('select derivative() from "log"')
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
'Overflow detected while using sum\(\)\.'):
await self.client0.query('select sum(now) from "huge"')
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
'Max depth reached in \'where\' expression!'):
await self.client0.query(
'select * from "aggr" where ((((((length > 1))))))')
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
'Cannot compile regular expression.*'):
await self.client0.query(
'select * from /(bla/')
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
'Memory allocation error or maximum recursion depth reached.'):
await self.client0.query(
'select * from "aggr" where length > {}'.format('(' * 500))
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
'Query too long.'):
await self.client0.query('select * from "{}"'.format('a' * 65535))
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
'Error while merging points. Make sure the destination '
'series name is valid.'):
self.assertIn('aggr-maximum', result)
await self.client0.query('alter database set select_points_limit 10')
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
'Query has reached the maximum number of selected points.*'):
await self.client0.query(
if __name__ == '__main__':
- SiriDB.LOG_LEVEL = 'CRITICAL'
- Server.HOLD_TERM = True
- Server.MEM_CHECK = True
- Server.TERMINAL = 'XTERM'
- Server.BUILDTYPE = 'Debug'
+ parse_args()
run_test(TestSelect())
'integer': [
[1538660000, 1],
[1538660010, 35.6],
- [1538660020, "-50,6%"],
+ [1538660020, "-50%"],
[1538660030, ""],
[1538660035, "garbage"],
[1538660040, "18446744073709551616"],
'double': [
[1538660000, 1.0],
[1538660010, -35],
- [1538660010, "-50,6%"],
+ [1538660010, "-50%"],
[1538660030, ""],
[1538660035, "garbage"],
]
'double': [
[1538660000, 1.0],
[1538660010, -35.0],
- [1538660010, -50.6],
+ [1538660010, -50.0],
[1538660030, 0.0],
- [1538660035, 0],
+ [1538660035, 0.0],
]
}
result = await self.client1.query('list servers log_level')
self.assertEqual(result.pop('servers'), [['debug'], ['debug']])
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
"Query error at position 42. Expecting "
"debug, info, warning, error or critical"):
await self.db.add_replica(self.server2, 1)
await self.assertIsRunning(self.db, self.client0, timeout=10)
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
"Cannot remove server 'localhost:9010' "
"because this is the only server for pool 0"):
await self.client1.query('drop server "localhost:9010"')
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
"Cannot remove server 'localhost:9012' "
"because the server is still online.*"):
with self.assertRaises(QueryError):
await self.client0.query('create user "sasientje" ')
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
'User name should be at least 2 characters.'):
await self.client0.query('create user "s" set password "123456" ')
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
'User name contains illegal characters.*'):
await self.client0.query('create user " " set password "123456" ')
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
'Password should be at least 4 characters.'):
await self.client0.query('create user "aa" set password "123" ')
result = await self.server0.stop()
self.assertTrue(result)
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
"Password should be at least 4 characters."):
result = await self.client1.query(
result = await self.client0.query("show who_am_i ")
self.assertEqual(result['data'][0]['value'], 'sasientje')
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
UserAuthError,
"Access denied. User 'sasientje' has no 'insert' privileges."):
result = await self.client0.insert({'no access test': [[1, 1.0]]})
result = await self.client0.query('count users where name == "pee"')
self.assertEqual(result.pop('users'), 1, msg='Expecting 1 user (pee)')
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
UserAuthError,
"Access denied. User 'sasientje' has no 'grant' privileges."):
result = await self.client0.query('grant full to user "pee" ')
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
"User name should be at least 2 characters."):
result = await self.client1.query('alter user "pee" set name "p" ')
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
"^User name contains illegal characters.*"):
result = await self.client1.query(
'alter user "pee" set name " p " ')
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
"User 'iris' already exists."):
result = await self.client1.query(
'alter user "pee" set name "iris" ')
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
"User 'iris' already exists."):
result = await self.client1.query(
'alter user "pee" set name "iris" ')
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
QueryError,
"Cannot find user: 'Pee'"):
result = await self.client1.query(
from .testbase import TestBase
from .series import Series
from .pipe_client import PipeClient as SiriDBAsyncUnixConnection
+from .args import parse_args
+
+SPINNER1 = \
+ ('▁', '▂', '▃', '▄', '▅', '▆', '▇', '█', '▇', '▆', '▅', '▄', '▃', '▁')
+SPINNER2 = \
+ ('⠁', '⠂', '⠄', '⡀', '⢀', '⠠', '⠐', '⠈')
+SPINNER3 = \
+ ('◐', '◓', '◑', '◒')
+
+
+class Spinner():
+
+ def __init__(self, charset=SPINNER3):
+ self._idx = 0
+ self._charset = charset
+ self._len = len(charset)
+
+ @property
+ def next(self):
+ char = self._charset[self._idx]
+ self._idx += 1
+ self._idx %= self._len
+ return char
+
+
+class Task():
+ def __init__(self, title):
+ self.running = True
+ self.task = asyncio.ensure_future(self.process())
+ self.success = False
+ self.title = title
+ self.start = time.time()
+
+ def stop(self, success):
+ self.running = False
+ self.success = success
+ self.duration = time.time() - self.start
+
+ async def process(self):
+ spinner = Spinner()
+ while self.running:
+ sys.stdout.write(f'{self.title:.<76}{spinner.next}\r')
+ sys.stdout.flush()
+ await asyncio.sleep(0.2)
+
+ if self.success:
+ print(f'{self.title:.<76}OK ({self.duration:.2f} seconds)')
+ else:
+ print(f'{self.title:.<76}FAILED ({self.duration:.2f} seconds)')
async def _run_test(test, loglevel):
logger = logging.getLogger()
logger.setLevel(loglevel)
-
- start = time.time()
- print('{:.<76}'.format(test.title), end='')
- sys.stdout.flush()
+ task = Task(test.title)
try:
await test.run()
except Exception as e:
- print('FAILED ({:.2f} seconds)'.format(time.time() - start))
+ task.stop(success=False)
raise e
else:
- print('OK ({:.2f} seconds)'.format(time.time() - start))
+ task.stop(success=True)
logger.setLevel('CRITICAL')
+ await task.task
+
def run_test(test, loglevel='CRITICAL'):
assert isinstance(test, TestBase)
--- /dev/null
+import argparse
+from .server import Server
+
+
+def parse_args():
+ parser = argparse.ArgumentParser()
+
+ parser.add_argument(
+ '-t', '--terminal',
+ choices=['xterm', 'xfce4-terminal'],
+ default=None,
+ help='Start SiriDB servers in a terminal. If no terminal is given '
+ 'process put their output in log files.')
+
+ parser.add_argument(
+ '-m', '--mem-check',
+ action='store_true',
+ help='Use `valgrind` for memory errors and leaks.')
+
+ parser.add_argument(
+ '-k', '--keep',
+ action='store_true',
+ help='Only valid when a terminal is used. This will keep the terminal '
+ 'open.')
+
+ parser.add_argument(
+ '-b', '--build',
+ choices=['Release', 'Debug'],
+ default='Release',
+ help='Choose either the Release or Debug build.')
+
+ parser.add_argument(
+ '-l', '--log-level',
+ default='critical',
+ help='set the log level',
+ choices=['debug', 'info', 'warning', 'error', 'critical'])
+
+ args = parser.parse_args()
+
+ Server.MEM_CHECK = args.mem_check
+ Server.HOLD_TERM = args.keep
+ Server.TERMINAL = args.terminal
+ Server.BUILDTYPE = args.build
+ Server.LOG_LEVEL = args.log_level.upper()
def __init__(self,
n,
+ title,
optimize_interval=300,
heartbeat_interval=30,
buffer_sync_interval=500,
pipe_name=None,
**unused):
self.n = n
+ self.test_title = title.lower().replace(' ', '_')
self.compression = compression
self.enable_pipe_support = int(bool(pipe_name))
self.pipe_name = \
async def start(self, sleep=None):
prev = self._get_pid_set()
-
- if self.TERMINAL == 'XFCE4_TERMINAL':
- rc = subprocess.Popen(
+ if self.TERMINAL == 'xfce4-terminal':
+ self.proc = subprocess.Popen(
'xfce4-terminal -e "{}{} --config {} --log-colorized"'
' --title {} --geometry={}{}'
.format(VALGRIND if self.MEM_CHECK else '',
self.GEOMETRY,
' -H' if self.HOLD_TERM else ''),
shell=True)
- elif self.TERMINAL == 'XTERM':
- rc = subprocess.Popen(
+ elif self.TERMINAL == 'xterm':
+ self.proc = subprocess.Popen(
'xterm {}-title {} -geometry {} -e "{}{} --config {}"'
.format('-hold ' if self.HOLD_TERM else '',
self.name,
self.cfgfile),
shell=True)
else:
- with open(f'{self.name}-err.log', 'a') as err:
- with open(f'testdir/{self.name}-out.log', 'a') as out:
- rc = subprocess.Popen(
+ with open(
+ f'testdir/{self.test_title}-{self.name}-err.log',
+ 'a') as err:
+ with open(
+ f'testdir/{self.test_title}-{self.name}-out.log',
+ 'a') as out:
+ self.proc = subprocess.Popen(
'{}{} --config {}'
.format(VALGRIND if self.MEM_CHECK else '',
SIRIDBC.format(BUILDTYPE=self.BUILDTYPE),
stderr=err,
stdout=out,
shell=True)
- self.assertEqual(rc, 0)
await asyncio.sleep(5)
await asyncio.sleep(1.0)
timeout -= 1
+ self.proc.communicate()
+ assert (self.proc.returncode == 0)
+
if timeout:
self.pid = None
return True
async def wrapped(self):
self.db = SiriDB(**kwargs)
- self.servers = [Server(n, **kwargs) for n in range(nservers)]
+ self.servers = [
+ Server(n, title=self.title, **kwargs) for n in range(nservers)]
for n, server in enumerate(self.servers):
setattr(self, 'server{}'.format(n), server)
setattr(self, 'client{}'.format(n), Client(self.db, server))
'Expecting a point to be a list of 2 items'
super().assertEqual(a[series][i][0], point[0])
if isinstance(a[series][i][1], str):
- super().assertEqual(a[series][i][1], point[1])
+ super().assertEqual(
+ a[series][i][1].replace(',', '.'),
+ point[1].replace(',', '.'))
elif math.isnan(a[series][i][1]):
assert math.isnan(point[1]), \
'Expecting point `{}` to be `nan`, got: `{}`' \